import  wx
import wx.lib.agw.pybusyinfo as PBI
import os
from collections import Counter
import  string as _string
import get_appdata_folder
from Bio.Align.Applications import ClustalwCommandline
from Bio.Seq import Seq
from Bio.Alphabet import IUPAC

BUFFERED = 1
help_path = os.getcwd()

appdata_path = get_appdata_folder.get_appdata_directory()

class MyCanvas(wx.ScrolledWindow):
    """Class for drawing the line chart."""
    def __init__(self, parent, ids, id = -1, size = wx.DefaultSize):
        wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)
        self.lines = []
        self.ids = ids
        self.maxWidth  = 1000
        self.maxHeight = 200*len(self.ids)

        self.x = self.y = 0
        self.curLine = []
        self.drawing = False
        self.SetCursor(wx.CROSS_CURSOR)
        self.SetBackgroundColour("WHITE")

        self.SetVirtualSize((self.maxWidth, self.maxHeight))
        self.SetScrollRate(20,20)

        if BUFFERED:
            self.buffer = wx.EmptyBitmap(self.maxWidth, self.maxHeight)
            dc = wx.BufferedDC(None, self.buffer)
            dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
            dc.Clear()
            dc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
            dc.DrawText('Potential siRNA hits to:', 80, 60)
            y = 80                                                  # pos of plot
            h = 175                                                 # pos of x scale
            margin_plot = y*180/100                                 # hight margin
            margin_xscale = h*80/100                                # hight margin
            # Get plotting values
            dummy_line = 180
            for plot_hits in self.ids:
                
                plott_all = self.make_all_plot(plot_hits)
                plot_eff = self.make_eff_plot(plot_hits)

                self.DoDrawing(dc, y=y, h=h, title=plot_hits, lst=plott_all, lst2=plot_eff)
                dc.SetPen(wx.Pen('BLACK', 2))
                dc.DrawLine(80, dummy_line, 980, dummy_line)
                dummy_line = dummy_line + 144
                y = y + margin_plot                                 # new pos of the next plot
                h = h + margin_xscale + 4                           # new pos of the next x scale

        self.Bind(wx.EVT_PAINT, self.OnPaint)

    def make_all_plot(self, id):
        "Count all hits per position and append to a list for plotting."
        f_bowtie = open(appdata_path + '\\files\\bowtie_parsed.txt', 'r')
        data = f_bowtie.readlines()
        f_seq = open(appdata_path + '\\files\\query_seq.txt', 'r')
        self.query_sequence = f_seq.read()
        f_seq.close()
        f_bowtie.close()

        l_all = []
        self.plot_all = []

        for i in data:
            i = i.strip()
            i = i.split('\t')
            if i[2] == id:
                start = self.query_sequence.find(str(i[3]))
                if start == -1:
                    myseq = Seq(str(i[3]), IUPAC.unambiguous_dna)
                    myseq = myseq.reverse_complement()
                    start = self.query_sequence.find(str(myseq))
                numbers = range(int(start),int(start)+21)
                for x in numbers:
                    l_all.append(x)

        l_all.sort()
        counter_all = Counter(l_all)
        counter_dict = dict(counter_all)
        for pos in range(len(self.query_sequence)+1):
            if counter_dict.get(pos) == None:
                self.plot_all.append((pos, 0))
            else:
                self.plot_all.append((pos, counter_dict.get(pos)))


        return self.plot_all

    def make_eff_plot(self, id):
        "Count efficient hits per position and append to a list for plotting."
        f_bowtie = open(appdata_path + '\\files\\bowtie_parsed.txt', 'r')
        data = f_bowtie.readlines()
        f_seq = open(appdata_path + '\\files\\query_seq.txt', 'r')
        self.query_sequence = f_seq.read()
        f_seq.close()
        f_bowtie.close()

        l_eff = []
        self.plot_eff = []

        for i in data:
            i = i.strip()
            i = i.split('\t')
            if i[2] == id:
                if i[4] == 'EFF':
                    start = self.query_sequence.find(str(i[3]))
                    if start == -1:
                        myseq = Seq(str(i[3]), IUPAC.unambiguous_dna)
                        myseq = myseq.reverse_complement()
                        start = self.query_sequence.find(str(myseq))
                    numbers = range(int(start),int(start)+21)
                    for x in numbers:
                        l_eff.append(x)

        l_eff.sort()
        counter_eff = Counter(l_eff)
        counter_dict = dict(counter_eff)
        for pos in range(len(self.query_sequence)+1):
            if counter_dict.get(pos) == None:
                self.plot_eff.append((pos, 0))
            else:
                self.plot_eff.append((pos, counter_dict.get(pos)))

        return self.plot_eff


    def OnPaint(self, event):
        if BUFFERED:
            dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)
        else:
            dc = wx.PaintDC(self)
            self.PrepareDC(dc)
            y = 80                                      # pos of plot
            h = 175                                     # pos of x scale

            margin_plot = y*180/100                     # hight margin
            margin_xscale = h*80/100                    # hight margin
            # Get plotting data
            dummy_line = 180
            for plot_hits in self.ids:
                plott_all = self.make_all_plot(plot_hits)
                plot_eff = self.make_eff_plot(plot_hits)

                self.DoDrawing(dc, y=y, h=h, title=plot_hits, lst=plott_all, lst2=plot_eff)
                dc.SetPen(wx.Pen('BLACK', 2))
                dc.DrawLine(80, dummy_line, 980, dummy_line)
                dummy_line = dummy_line + 144
                y = y + margin_plot                     # new pos of the next plot
                h = h + margin_xscale + 4               # new pos of the next x scale

    def DoDrawing(self, dc, y, title, h, lst, lst2, printing=False):
        dc.BeginDrawing()

        # Rectangle for plot frame
        dc.SetPen(wx.Pen('BLACK', 1))

        x = 80                                          # move plot left and right
        #y = 100                                        # move plot up and down
        length = 900                                    # length of plots
        hight = 100                                     # hight of plots

        dc.SetBrush(wx.Brush((255, 250, 205)))
        dc.DrawRectangle(x, y, length, hight+1)

        dc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        dc.DrawText(title, 85, y+1)

        # Plotting line for line chart 1
        final_lst = []

        # Calculate maximum hight of the y-scale
        max_lst = []
        for m in lst:
            max_lst.append(m[1])
        max_y = max(max_lst)
        if max_y > 21:
            max_y = max_y
        else:
            max_y = 21
        for i in lst:
            # Scaling of the coordinates
            coord1 = i[0]*length/len(lst)
            coord2 = -i[1]*(hight*75/100)/max_y
            final_lst.append((coord1, coord2))

        dc.SetPen(wx.Pen('Blue', 2))
        dc.DrawLines(final_lst, x+1, y+hight)

        # Plotting line for line chart 2
        final_lst2 = []

        for i2 in lst2:
            # Scaling of the coordinates
            coord1_2 = i2[0]*length/len(lst2)
            coord2_2 = -i2[1]*(hight*75/100)/max_y
            final_lst2.append((coord1_2, coord2_2))
        dc.SetPen(wx.Pen('Red', 2))
        dc.DrawLines(final_lst2, x+1, y+hight)

        self.draw_xscale(dc, h, lst, max_y)
        self.draw_legend(dc)
        dc.EndDrawing()

    def draw_legend(self, dc):
        start = 80
        x_length = 900
        y_length = 30
        dc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL))
        dc.SetBrush(wx.Brush((255, 255, 255)))
        dc.DrawRectangle(start, 10, x_length, y_length)
        # x-axe
        dc.DrawText('X-axis = Query sequence coordinates', start+10, y_length/2+2)
        # y-axe
        dc.DrawText('Y-axis = Number of siRNA with hits to the subject', start+250, y_length/2+2)
        # All hits
        dc.SetPen(wx.Pen('Blue', 1))
        dc.SetBrush(wx.Brush('Blue'))
        dc.DrawRectangle(start+560, 20, 10, 10)
        dc.DrawText('Total number of siRNA hits', start+580, y_length/2+2)
        # Eff hits
        dc.SetPen(wx.Pen('RED', 1))
        dc.SetBrush(wx.Brush('RED'))
        dc.DrawRectangle(start+760, 20, 10, 10)
        dc.DrawText('Efficient siRNA hits', start+780, y_length/2+2)

    def draw_xscale(self, dc, h, lst, max_y):
        length = 900
        # Add x scale
        dc.SetPen(wx.Pen('BLACK', 1))

        if len(lst) <= 101:
            split = 10
        elif len(lst) >= 101 and len(lst) <= 201:
            split = 20
        elif len(lst) >= 201 and len(lst) <= 501:
            split = 50
        elif len(lst) >= 501 and len(lst) <= 1001:
            split = 100
        elif len(lst) >= 1001:
            split = 200

        x_start = 80                                    # start of the axes at 0
        margin = split*length/len(lst)                  # calc the margin of each axe, scaled
        nr_axes = float(len(lst))/float(split)          # nr of axes dep. on seq length

        nr_axes = round(nr_axes, 0)
        dc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        label = 0
        for line in range(int(nr_axes)+1):
            dc.DrawLine(x_start, h, x_start, h+5)
            dc.SetPen(wx.Pen('BLACK', 2))
            dc.SetPen(wx.Pen('BLACK', 1))
            dc.DrawText(str(label), x_start-10, h+10)
            x_start = x_start + margin + 1
            label = label + split
            if x_start > 981:
                break

        dc.DrawLine(76, h-70, 76+10, h-70)
        dc.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        dc.DrawText(str(max_y), 55, h-80)

    def getWidth(self):
        return self.maxWidth

    def getHeight(self):
        return self.maxHeight

    def SaveFile(self, fileName= ''):
        if _string.lower(fileName[-3:]) not in ['bmp','xbm','xpm','png','jpg']:
            dlg1 = wx.FileDialog(
                    self,
                    "Choose a file with extension bmp, gif, xbm, xpm, png, or jpg", ".", "",
                    "BMP files (*.bmp)|*.bmp|XBM files (*.xbm)|*.xbm|XPM file (*.xpm)|*.xpm|PNG files (*.png)|*.png|JPG files (*.jpg)|*.jpg",
                    wx.SAVE|wx.OVERWRITE_PROMPT
                    )
            try:
                while 1:
                    if dlg1.ShowModal() == wx.ID_OK:
                        fileName = dlg1.GetPath()
                        # Check for proper extension
                        if _string.lower(fileName[-3:]) not in ['bmp','xbm','xpm','png','jpg']:
                            dlg2 = wx.MessageDialog(self, 'File name extension\n'
                            'must be one of\n'
                            'bmp, xbm, xpm, png, or jpg',
                              'File Name Error', wx.OK | wx.ICON_ERROR)
                            try:
                                dlg2.ShowModal()
                            finally:
                                dlg2.Destroy()
                            dlg_save = wx.MessageDialog(self, 'Image saved!','Saved',wx.OK | wx.ICON_INFORMATION)
                            dlg_save.ShowModal()
                            dlg_save.Destroy()
                        else:
                            break
                                                        # Now save file
                    else:
                                                        # Exit without saving
                        return False
            finally:
                dlg1.Destroy()#


        # File name has required extension
        fType = _string.lower(fileName[-3:])
        if fType == "bmp":
            tp= wx.BITMAP_TYPE_BMP                      # Save a Windows bitmap file.
        elif fType == "xbm":
            tp= wx.BITMAP_TYPE_XBM                      # Save an X bitmap file.
        elif fType == "xpm":
            tp= wx.BITMAP_TYPE_XPM                      # Save an XPM bitmap file.
        elif fType == "jpg":
            tp= wx.BITMAP_TYPE_JPEG                     # Save a JPG file.
        else:
            tp= wx.BITMAP_TYPE_PNG                      # Save a PNG file.
        # Save Bitmap
        res= self.buffer.SaveFile(fileName, tp)
        return res

class MyPrintout(wx.Printout):
    def __init__(self, canvas, ids):
        wx.Printout.__init__(self)
        self.canvas = canvas
        self.margins = (wx.Point(15,15), wx.Point(15,15))
        self.lines = 150*32
        self.ids = ids

    def HasPage(self, page):
        return page <= self.numPages

    def GetPageInfo(self):
        return (1, self.numPages, 1, self.numPages)


    def CalculateScale(self, dc):
        # Scale the DC such that the printout is roughly the same as
        # the screen scaling.
        ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
        ppiScreenX, ppiScreenY = self.GetPPIScreen()
        logScale = float(ppiPrinterX)/float(ppiScreenX)

        # Now adjust if the real page size is reduced (such as when
        # drawing on a scaled wx.MemoryDC in the Print Preview.)  If
        # page width == DC width then nothing changes, otherwise we
        # scale down for the DC.
        pw, ph = self.GetPageSizePixels()
        dw, dh = dc.GetSize()
        scale = logScale * float(dw)/float(pw)

        # Set the DC's scale.
        dc.SetUserScale(scale, scale)

        # Find the logical units per millimeter (for calculating the
        # margins)
        self.logUnitsMM = float(ppiPrinterX)/(logScale*25.4)


    def CalculateLayout(self, dc):
        # Determine the position of the margins and the
        # page/line height
        topLeft, bottomRight = self.margins
        dw, dh = dc.GetSize()
        self.x1 = topLeft.x * self.logUnitsMM
        self.y1 = topLeft.y * self.logUnitsMM
        self.x2 = dc.DeviceToLogicalXRel(dw) - bottomRight.x * self.logUnitsMM
        self.y2 = dc.DeviceToLogicalYRel(dh) - bottomRight.y * self.logUnitsMM

        # use a 1mm buffer around the inside of the box, and a few
        # pixels between each line
        self.pageHeight = self.y2 - self.y1 - 2*self.logUnitsMM
        FONTSIZE = 10
        font = wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
        dc.SetFont(font)
        self.lineHeight = dc.GetCharHeight()
        #self.linesPerPage = int(self.pageHeight/self.lineHeight)
        self.linesPerPage = 8*150

    def OnPreparePrinting(self):
        # calculate the number of pages
        dc = self.GetDC()
        self.CalculateScale(dc)
        self.CalculateLayout(dc)
        self.numPages = self.lines / self.linesPerPage
        if self.lines % self.linesPerPage != 0:
            self.numPages += 1
        self.numPages = 1

    def make_all_plot(self, id):
        "Count all hits per position and append to a list for plotting."
        f_bowtie = open(appdata_path + '\\files\\bowtie_parsed.txt', 'r')
        data = f_bowtie.readlines()
        f_seq = open(appdata_path + '\\files\\query_seq.txt', 'r')
        self.query_sequence = f_seq.read()
        f_seq.close()
        f_bowtie.close()

        l_all = []
        self.plot_all = []

        for i in data:
            i = i.strip()
            i = i.split('\t')
            if i[2] == id:
                start = self.query_sequence.find(str(i[3]))
                if start == -1:
                    myseq = Seq(str(i[3]), IUPAC.unambiguous_dna)
                    myseq = myseq.reverse_complement()
                    start = self.query_sequence.find(str(myseq))
                numbers = range(int(start),int(start)+21)
                for x in numbers:
                    l_all.append(x)

        l_all.sort()
        counter_all = Counter(l_all)
        counter_dict = dict(counter_all)
        for pos in range(len(self.query_sequence)+1):
            if counter_dict.get(pos) == None:
                self.plot_all.append((pos, 0))
            else:
                self.plot_all.append((pos, counter_dict.get(pos)))

        return self.plot_all

    def make_eff_plot(self, id):
        "Count efficient hits per position and append to a list for plotting."
        f_bowtie = open(appdata_path + '\\files\\bowtie_parsed.txt', 'r')
        data = f_bowtie.readlines()
        f_seq = open(appdata_path + '\\files\\query_seq.txt', 'r')
        self.query_sequence = f_seq.read()
        f_seq.close()
        f_bowtie.close()

        l_eff = []
        self.plot_eff = []

        for i in data:
            i = i.strip()
            i = i.split('\t')
            if i[2] == id:
                if i[4] == 'EFF':
                    start = self.query_sequence.find(str(i[3]))
                    if start == -1:
                        myseq = Seq(str(i[3]), IUPAC.unambiguous_dna)
                        myseq = myseq.reverse_complement()
                        start = self.query_sequence.find(str(myseq))
                    numbers = range(int(start),int(start)+21)
                    for x in numbers:
                        l_eff.append(x)

        l_eff.sort()
        counter_eff = Counter(l_eff)
        counter_dict = dict(counter_eff)
        for pos in range(len(self.query_sequence)+1):
            if counter_dict.get(pos) == None:
                self.plot_eff.append((pos, 0))
            else:
                self.plot_eff.append((pos, counter_dict.get(pos)))

        return self.plot_eff


    def OnPrintPage(self, page):
        dc = self.GetDC()

        plot_index_start = 0
        plot_index_end = 8
        line = (page-1) * self.linesPerPage
        if line < (page * self.linesPerPage):

            y = 80                                      # pos of plot
            h = 175                                     # pos of x scale

            margin_plot = y*180/100                     # hight margin
            margin_xscale = h*80/100                    # hight margin

            # Get plotting data
            dummy_line = 180
            all_names = self.ids
            for plot_hits in all_names[plot_index_start:plot_index_end]:

                plott_all = self.make_all_plot(plot_hits)
                plot_eff = self.make_eff_plot(plot_hits)

                self.canvas.DoDrawing(dc, y=y, h=h, title=plot_hits, lst=plott_all, lst2=plot_eff)
                dc.SetPen(wx.Pen('BLACK', 2))
                dc.DrawLine(80, dummy_line, 980, dummy_line)
                dummy_line = dummy_line + 144
                y = y + margin_plot                     # new pos of the next plot
                h = h + margin_xscale + 4               # new pos of the next x scale


                line += 1
                plot_index_start = plot_index_start + 1
                plot_index_end = plot_index_end + 1
                #print plot_index_end, plot_index_start, line
                if line >= self.lines:
                    break

        #dc.DrawText("Page: %d" % page, marginX/2, maxY-marginY+200)
        #dc.DrawText("siRNA Scan results", marginX/2, maxY-marginY-1130)

        return True


class PlottingFrame(wx.Frame):
    def __init__(self, ids):
        wx.Frame.__init__(self, None, -1, "si-Fi scan results", size=(1100, 800))
        self.ids = ids
        self.printData = wx.PrintData()
        self.printData.SetPaperId(wx.PAPER_LETTER)
        self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
        self.printData.SetOrientation(wx.PORTRAIT)
        self.box = wx.BoxSizer(wx.VERTICAL)
        self.canvas = MyCanvas(self, ids)
        self.box.Add(self.canvas, 1, wx.GROW)
        self.SetAutoLayout(True)
        self.SetSizer(self.box)
        self.build_menu()
        # Statusbar
        # Create Statusbar
        self.CreateStatusBar(1)
        self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)

    def OnMouseLeftDown(self,event):
        # Raw coord
        pos = event.GetPosition()

        # Sequence coordinates
        seq_length = open(appdata_path + '\\files\\seq_length.txt', 'r')
        seq_len = seq_length.read()
        seq_pos = (pos[0]-80)/(900/float(seq_len))-1
        seq_pos = int(seq_pos)
        self.SetStatusText("Sequence Position: " + str(seq_pos))
        event.Skip()

    def build_menu(self):
        # Create Menu Bar
        self.menuBar = wx.MenuBar()
        # Create Menu1 from left
        menu1 = wx.Menu()
        menu1.Append(101, "Print", 'Print all plots')
        menu1.Append(102, 'Save Plot...', 'Save all plot')
        menu1.Append(103, 'E&xit', 'Enough of this already!')
        # Create Menu2 from left
        menu2 = wx.Menu()
        menu2.Append(300, 'Help', 'Help')
        # Create Menu3 from left
        menu3 = wx.Menu()
        # Open File for Menu names of hits
        #f_menu = open(appdata_path + '\\files\\data_hits.txt', 'r')
        hits = self.ids
        id = 400
        for menu_id in hits:
            menu_id = menu_id.strip()
            menu_id = menu_id.split('\t')
            menu3.Append(id, str(menu_id[0]), str(menu_id[0]))
            self.Bind(wx.EVT_MENU, self.do_alignment, id=id)
            id = id + 1
        # Append all Menus
        self.menuBar.Append(menu1, "File")
        self.menuBar.Append(menu3, "Alignment")
        self.menuBar.Append(menu2, '&Help')

        # # Bind all  Menus
        self.Bind(wx.EVT_MENU, self.OnPrintPreview, id=101)
        self.Bind(wx.EVT_MENU, self.OnSaveFile, id=102)
        self.Bind(wx.EVT_MENU, self.OnFileExit, id=103)
        self.Bind(wx.EVT_MENU, self.OnHelp, id=300)

        self.SetMenuBar(self.menuBar)

    def do_alignment(self, event):
        # Get hit
        menuItem = self.menuBar.FindItemById(event.GetId())
        menuItem = '>' + menuItem.GetText()[0:]
        # Get DB
        f_db = open(appdata_path + '\\files\\last_db.txt', 'r')
        db = f_db.read() + '_index'
        # Get query sequence
        f_seq = open(appdata_path + '\\files\\query_seq.txt', 'r')
        query_seq = f_seq.read()
        # Switch to appdata folder
        os.chdir(appdata_path + '\\database\\')
        busy2 = PBI.PyBusyInfo('Please wait.\nDepending on sequence length, it will take awhile.', parent=None, title="Creating Alignment")
        wx.Yield()
        cursor = wx.StockCursor(wx.CURSOR_WAIT)
        self.SetCursor(cursor)

        cmd = "bowtie-inspect -a 0 " + db
        lst = os.popen(cmd).readlines()
        try:
            index = lst.index(menuItem + '\n')
            hit_seq = lst.pop(index+1)
            f_align = open(appdata_path + '\\database\\clustalw_input.txt', 'w')
            f_align.write('>RNAi_query_sequence\n')
            f_align.write(query_seq + '\n')
            f_align.write(menuItem + '\n')
            f_align.write(hit_seq)
            f_align.close()

            # Start clustalw alignment
            clustalw_exe = appdata_path + '\\database\\clustalw2.exe'
            clustalw_cline = ClustalwCommandline(clustalw_exe, infile="clustalw_input.txt")
            stdout, stderr = clustalw_cline()

            # Open alignment
            f_align = open(appdata_path + '\\database\\clustalw_input.aln', 'r')
            align = f_align.read()
            del busy2
            cursor = wx.StockCursor(wx.CURSOR_DEFAULT)
            self.SetCursor(cursor)
            dlg_align = wx.lib.dialogs.ScrolledMessageDialog(self, str(align), "Pairwise Alignment",
                                                            size = (1000,800))

            children = dlg_align.GetChildren()
            textCtrl = children[0]
            textCtrl.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, "Courier New"))
            dlg_align.ShowModal()
            dlg_align.Destroy()

        except ValueError:
            dlg = wx.MessageDialog(self, 'Sorry, hit not found in database.',
                               'Not found',
                               wx.OK | wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()



    def OnSaveFile(self, event):
        self.canvas.SaveFile()

    def OnFileExit(self, event):
        self.Close()

    def OnHelp(self, event):
        self.InitHelp()

    def InitHelp(self):
        def _addBook(filename):
            if not self.help.AddBook(filename):
                wx.MessageBox("Unable to open: " + filename,
                              "Error", wx.OK|wx.ICON_EXCLAMATION)

        self.help = wx.html.HtmlHelpController()

        _addBook(help_path + "\\help\\testing.hhp")
        self.OnShowHelpContents()

    def OnShowHelpContents(self):
        self.help.Display(help_path + "\\help\\graphic.html")

    def OnPrintPreview(self, event):
        data = wx.PrintDialogData(self.printData)
        printout = MyPrintout(self.canvas, self.ids)
        printout2 = MyPrintout(self.canvas, self.ids)
        self.preview = wx.PrintPreview(printout, printout2, data)

        if not self.preview.Ok():
            return

        pfrm = wx.PreviewFrame(self.preview, self, "This is a print preview")

        pfrm.Initialize()
        pfrm.SetPosition(self.GetPosition())
        pfrm.SetSize(self.GetSize())
        pfrm.Show(True)

#if __name__ == '__main__':
#    app = wx.PySimpleApp()
#    frame = PlottingFrame()
#    frame.Show(True)
#    app.MainLoop()